package utils

import (
	"net"
	"server/global"
	"server/model/appTypes"
	"server/model/request"

	"github.com/gin-gonic/gin"
	"github.com/gofrs/uuid"
	"go.uber.org/zap"
)

// SetRefreshToken 设置Refresh Token的cookie
func SetRefreshToken(c *gin.Context, token string, maxAge int) {
	host, _, err := net.SplitHostPort(c.Request.Host)
	if err != nil {
		host = c.Request.Host
	}
	// 设置 refresh-token，name为 x-refresh-token
	setCookie(c, "x-refresh-token", token, maxAge, host)
}

// ClearRefreshToken 清除Refresh Token的cookie
func ClearRefreshToken(c *gin.Context) {
	host, _, err := net.SplitHostPort(c.Request.Host)
	if err != nil {
		host = c.Request.Host
	}
	// 设置 refresh-token，name为 x-refresh-token, 设置token的值为""
	setCookie(c, "x-refresh-token", "", -1, host)
}

// gin 上下文中设置cookie, httpOnly 方式，前端js不能直接访问，防止xss攻击
func setCookie(c *gin.Context, name, value string, maxAge int, host string) {
	// host是否是ip地址,设置cookie的domain为"",如果是域名设置为 host（域名）
	if net.ParseIP(host) != nil {
		c.SetCookie(name, value, maxAge, "/", "", false, true)
	} else {
		c.SetCookie(name, value, maxAge, "/", host, false, true)
	}
}

// GetAccessToken 从请求头获取Access Token
func GetAccessToken(c *gin.Context) string {
	// 获取x-access-token头部值
	token := c.Request.Header.Get("x-access-token")
	return token
}

// GetRefreshToken 从cookie获取Refresh Token
func GetRefreshToken(c *gin.Context) string {
	// 尝试从cookie中获取refresh-token
	token, _ := c.Cookie("x-refresh-token")
	return token
}

// GetAccessTokenClaims 从Gin的Context中解析并获取JWT的Claims
func GetAccessTokenClaims(c *gin.Context) (*request.JwtCustomAccessClaims, error) {
	token := GetAccessToken(c)
	// 创建JWT实例
	j := NewJwt()
	// 解析Access Token
	claims, err := j.ParseAccessToken(token)
	if err != nil {
		// 如果解析失败，记录错误日志
		global.Log.Error("Failed to retrieve JWT parsing information from Gin's Context. Please check if the request header contains 'x-access-token' and if the claims structure is correct.", zap.Error(err))
	}
	return claims, err
}

// GetRefreshClaims 从Gin的Context中解析并获取Refresh Token的Claims
func GetRefreshClaims(c *gin.Context) (*request.JwtCustomRefreshClaims, error) {
	// 获取Refresh Token
	token := GetRefreshToken(c)
	// 创建JWT实例
	j := NewJwt()
	// 解析Refresh Token
	claims, err := j.ParseRefreshToken(token)
	if err != nil {
		// 如果解析失败，记录错误日志
		global.Log.Error("Failed to retrieve JWT parsing information from Gin's Context. Please check if the request header contains 'x-refresh-token' and if the claims structure is correct.", zap.Error(err))
	}
	return claims, err
}

// GetRoleID 从Gin的Context中获取JWT解析出来的用户角色ID
func GetRoleID(c *gin.Context) appTypes.RoleID {
	if claims, exist := c.Get("claims"); !exist {
		// 如果不存在，则重新解析Access Token
		if cl, err := GetAccessTokenClaims(c); err != nil {
			return 0
		} else {
			return cl.RoleID
		}
	} else {
		return claims.(*request.JwtCustomAccessClaims).RoleID
	}
}

//
//// GetUserInfo 从Gin的Context中获取JWT解析出来的用户信息（Claims）
//func GetUserInfo(c *gin.Context) *request.JwtCustomAccessClaims {
//	// 首先尝试从Context中获取"claims"
//	if claims, exists := c.Get("claims"); !exists {
//		// 如果不存在，则重新解析Access Token
//		if cl, err := GetAccessTokenClaims(c); err != nil {
//			// 如果解析失败，返回nil
//			return nil
//		} else {
//			// 返回解析出来的用户信息
//			return cl
//		}
//	} else {
//		// 如果已存在claims，则直接返回
//		return claims.(*request.JwtCustomAccessClaims)
//	}
//}

// GetUserID 从Gin的Context中获取JWT解析出来的用户ID
func GetUserID(c *gin.Context) uint {
	// 首先尝试从Context中获取"claims"
	if claims, exists := c.Get("claims"); !exists {
		// 如果不存在，则重新解析Access Token
		if cl, err := GetAccessTokenClaims(c); err != nil {
			// 如果解析失败，返回0
			return 0
		} else {
			// 返回解析出来的用户ID
			return cl.UserID
		}
	} else {
		// 如果已存在claims，则直接返回用户ID
		return claims.(*request.JwtCustomAccessClaims).UserID
	}
}

// GetUUID 从Gin的Context中获取JWT解析出来的用户UUID
func GetUUID(c *gin.Context) uuid.UUID {
	// 首先尝试从Context中获取"claims"
	if claims, exists := c.Get("claims"); !exists {
		// 如果不存在，则重新解析Access Token
		if cl, err := GetAccessTokenClaims(c); err != nil {
			// 如果解析失败，返回一个空UUID
			return uuid.UUID{}
		} else {
			// 返回解析出来的UUID
			return cl.UUID
		}
	} else {
		// 如果已存在claims，则直接返回UUID
		return claims.(*request.JwtCustomAccessClaims).UUID
	}
}
